use model_graph_types::channel::pubsub::Topic;

use std::{
    collections::HashMap,
    sync::{Arc, Mutex, RwLock},
};

lazy_static::lazy_static! {

    /// 拥有的话题
    pub(crate) static ref OWN_TOPICS: RwLock<HashMap<String, Arc<Mutex<Topic>>>> = RwLock::new(HashMap::new());

    /// 订阅的话题
    pub(crate) static ref SUB_TOPICS: RwLock<HashMap<String, Topic>> = RwLock::new(HashMap::new());
}

pub fn create_topic(topic: Topic) -> anyhow::Result<()> {
    //
    let topic_name = &topic.topic;
    if topic_exist(topic_name)? {
        return Ok(());
    }
    let cache_result = OWN_TOPICS
        .write()
        .map_err(|err| anyhow::anyhow!("获取锁失败:{}", err));

    match cache_result {
        Ok(mut cache) => {
            cache.insert(topic_name.to_lowercase(), Arc::new(Mutex::new(topic)));
            tracing::debug!("创建Topic成功!");
            Ok(())
        }
        Err(err) => {
            tracing::debug!("创建Topic失敗!{}", err);
            Ok(())
        }
    }
}

pub fn remove_topic(topic: &String) -> anyhow::Result<()> {
    //
    let exist = {
        let cache = OWN_TOPICS
            .read()
            .map_err(|err| anyhow::anyhow!("{}", err))?;
        cache.contains_key(&topic.to_lowercase())
    };
    if exist {
        let cache_result = OWN_TOPICS
            .write()
            .map_err(|err| anyhow::anyhow!("获取锁失败:{}", err));

        match cache_result {
            Ok(mut cache) => {
                cache.remove(&topic.to_lowercase());
                tracing::debug!("移除成功!");
                Ok(())
            }
            Err(err) => {
                tracing::debug!("移除失敗!{}", err);
                Ok(())
            }
        }
    } else {
        tracing::debug!("已经不存在!");
        Ok(())
    }
}

pub fn topic_exist(topic: &String) -> anyhow::Result<bool> {
    let exist = {
        let cache = OWN_TOPICS
            .read()
            .map_err(|err| anyhow::anyhow!("{}", err))?;
        cache.contains_key(&topic.to_lowercase())
    };
    Ok(exist)
}

pub fn get_topic(topic: &String) -> anyhow::Result<Arc<Mutex<Topic>>> {
    let cache = OWN_TOPICS
        .read()
        .map_err(|err| anyhow::anyhow!("{}", err))?;
    let arc_topic = cache
        .get(&topic.to_lowercase())
        .map_or(Err(anyhow::anyhow!("没有查询到")), |v| Ok(v))?;

    Ok(arc_topic.clone())
}

pub fn get_topic_subscribers(topic: &String) -> anyhow::Result<Vec<String>> {
    let arc_topic = get_topic(topic)?;
    let subscribers = arc_topic
        .lock()
        .map_err(|err| anyhow::anyhow!("{}", err))?
        .subscribers
        .clone();
    Ok(subscribers)
}

pub fn append_subscriber(topic: &String, peer_id: &String) -> anyhow::Result<()> {
    //
    if !topic_exist(topic)? {
        return Err(anyhow::anyhow!("topic不存在!{}", topic));
    }
    let cache_result = OWN_TOPICS
        .write()
        .map_err(|err| anyhow::anyhow!("获取锁失败:{}", err));

    match cache_result {
        Ok(mut cache) => {
            if let Some(topic_ref) = cache.get_mut(&topic.to_lowercase()) {
                let list = &mut topic_ref
                    .lock()
                    .map_err(|err| anyhow::anyhow!("{}", err))?
                    .subscribers;
                if !list.contains(peer_id) {
                    list.push(peer_id.clone());
                }
                tracing::debug!("添加subsciber成功!");
                return Ok(());
            }
        }
        Err(err) => {
            tracing::debug!("创建Topic失敗!{}", err);
        }
    }
    Err(anyhow::anyhow!("添加失败!"))
}

pub fn remove_subscriber(topic: &String, peer_id: &String) -> anyhow::Result<()> {
    //
    if !topic_exist(topic)? {
        return Err(anyhow::anyhow!("topic不存在!{}", topic));
    }
    let cache_result = OWN_TOPICS
        .write()
        .map_err(|err| anyhow::anyhow!("获取锁失败:{}", err));

    match cache_result {
        Ok(mut cache) => {
            if let Some(topic_ref) = cache.get_mut(&topic.to_lowercase()) {
                let list = &mut topic_ref
                    .lock()
                    .map_err(|err| anyhow::anyhow!("{}", err))?
                    .subscribers;
                if !list.contains(peer_id) {
                    list.retain(|p| p != peer_id);
                }
                tracing::debug!("添加subsciber成功!");
                return Ok(());
            }
        }
        Err(err) => {
            tracing::debug!("创建Topic失敗!{}", err);
        }
    }
    Err(anyhow::anyhow!("添加失败!"))
}

pub fn subscribe_topic(topic: Topic) -> anyhow::Result<()> {
    //
    let topic_name = &topic.topic;
    if topic_subscribed(topic_name)? {
        return Err(anyhow::anyhow!("已经存在!"));
    }
    let cache_result = SUB_TOPICS
        .write()
        .map_err(|err| anyhow::anyhow!("获取锁失败:{}", err));

    match cache_result {
        Ok(mut cache) => {
            cache.insert(topic_name.to_lowercase(), topic);
            tracing::debug!("创建Topic成功!");
            Ok(())
        }
        Err(err) => {
            tracing::debug!("创建Topic失敗!{}", err);
            Ok(())
        }
    }
}

pub fn topic_subscribed(topic: &String) -> anyhow::Result<bool> {
    let exist = {
        let cache = SUB_TOPICS
            .read()
            .map_err(|err| anyhow::anyhow!("{}", err))?;
        cache.contains_key(&topic.to_lowercase())
    };
    Ok(exist)
}

pub fn subscribed_topic(topic: &String) -> anyhow::Result<Option<Topic>> {
    let cache = SUB_TOPICS
        .read()
        .map_err(|err| anyhow::anyhow!("{}", err))?;
    Ok(cache
        .get(&topic.to_lowercase())
        .map_or(None, |t| Some(t.clone())))
}

pub fn unsubscribe_topic(topic: &String) -> anyhow::Result<()> {
    //
    let exist = {
        let cache = SUB_TOPICS
            .read()
            .map_err(|err| anyhow::anyhow!("{}", err))?;
        cache.contains_key(&topic.to_lowercase())
    };
    if exist {
        let cache_result = SUB_TOPICS
            .write()
            .map_err(|err| anyhow::anyhow!("获取锁失败:{}", err));

        match cache_result {
            Ok(mut cache) => {
                cache.remove(&topic.to_lowercase());
                tracing::debug!("移除成功!");
                Ok(())
            }
            Err(err) => {
                tracing::debug!("移除失敗!{}", err);
                Ok(())
            }
        }
    } else {
        tracing::debug!("已经不存在!");
        Ok(())
    }
}
